import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import "./input-number.scss";

/**
 * @param min 设置计数器允许的最小值
 * @param max 设置计数器允许的最大值
 * @param step 计数器步长
 * @param size 计数器尺寸
 * @param readonly 原生 readonly 属性，是否只读
 * @param disabled 是否禁用状态
 * @param placeholder 等价于原生 input placeholder 属性
 * @param controlsPosition 控制按钮位置
 * @param controls 是否使用控制按钮
 * @param name 等价于原生 input name 属性
 * @param reduceIcon 自定义输入框按钮减少图标
 * @param addIcon 自定义输入框按钮增加图标
 * @param defaultValue 默认显示值 
 * @param onBlur 失去焦点触发的函数
 * @param onFocus 获取焦点触发的函数
 * @param onChange 仅当输入值改变时，当输入框失去焦点或用户按Enter时触发
 * @param onInput 输入时触发的函数
 */
interface Props {
    min?: number,
    max?: number,
    step?: number,
    size?: 'default' | 'large' | 'small',
    readonly?: boolean,
    disabled?: boolean,
    placeholder?: string,
    controlsPosition?: 'default' | 'right',
    controls?: boolean,
    name?: string,
    reduceIcon?: React.ReactNode,
    addIcon?: React.ReactNode,
    defaultValue?: number,
    onBlur?: () => void,
    onFocus?: () => void,
    onChange?: (event: ChangeEvent<HTMLInputElement>) => void,
    onInput?: (event: FormEvent<HTMLInputElement>) => void
}

const InputNumber = ({
    min,
    max,
    step = 1,
    size = "default",
    readonly = false,
    disabled = false,
    placeholder,
    controlsPosition = "default",
    controls = true,
    name,
    reduceIcon,
    addIcon,
    defaultValue = 0,
    onBlur = () => { },
    onFocus = () => { },
    onChange = () => { },
    onInput = () => { }
}: Props) => {
    const [value, setValue] = useState<number>(defaultValue)

    // 获取焦点事件
    const [borderColor, setBorderColor] = useState<string>("")

    // 减
    const [reduceFlag, setReduceFlag] = useState<boolean>(false)
    const reduce = () => {
        if (min !== undefined) {
            if (value - step >= min) {
                setValue(value - step)
            }
        } else {
            setValue(value - step)
        }
    }

    // 加
    const [addFlag, setAddFlag] = useState<boolean>(false)
    const add = () => {
        if (max !== undefined) {
            if (value + step <= max) {
                setValue(value + step)
            }
        } else {
            setValue(value + step)
        }
    }

    useEffect(() => {
        if (min !== undefined) {
            setReduceFlag(value - step < min)
        }
        if (max !== undefined) {
            setAddFlag(value + step > max)
        }
    }, [value])
    return (
        <div className={["pe-input-number", `pe-input-number-${size}`].join(" ").trim()}
            style={{ '--pe-input-number-hover-border-color': disabled ? 'var(--pe-color-border)' : '' } as React.CSSProperties}>
            {
                controlsPosition === 'default' && controls ? (
                    <div
                        className={["pe-input-number-icon pe-input-number-left", reduceFlag ? 'pe-input-number-disabled' : ''].join(" ").trim()}
                        onClick={() => {
                            reduce()
                        }}>
                        {
                            !reduceIcon ? (
                                <i className="pe-icon">
                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                        <path fill="currentColor" d="M128 544h768a32 32 0 1 0 0-64H128a32 32 0 0 0 0 64"></path>
                                    </svg>
                                </i>
                            ) : (
                                <>{reduceIcon}</>
                            )
                        }
                    </div>
                ) : null
            }
            <div className="pe-input-number-wapper">
                <input type="number" className="pe-input-number-inner"
                    style={{ '--pe-input-number-border-color': borderColor } as React.CSSProperties} placeholder={placeholder}
                    disabled={disabled} min={min} max={max} readOnly={readonly} name={name} value={value}
                    onBlur={() => {
                        if (min !== undefined && value < min) {
                            setValue(min)
                        }
                        if (max !== undefined && value > max) {
                            setValue(max)
                        }
                        onBlur()
                    }}
                    onFocus={() => {
                        setBorderColor("var(--pe-color-primary)")
                        onFocus()
                    }}
                    onChange={(e) => {
                        onChange(e)
                    }}
                    onInput={(e) => {
                        setValue(Number((e.target as HTMLInputElement).value))                        
                        onInput(e)
                    }} />
                {
                    controlsPosition === 'right' && controls ? (
                        <div className="pe-input-number-position">
                            <div className={["pe-input-number-position-icon", addFlag ? 'pe-input-number-disabled' : ''].join(" ").trim()}
                                onClick={() => {
                                    add()
                                }}>
                                {
                                    !addIcon ? (
                                        <i className="pe-icon">
                                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                                <path fill="currentColor"
                                                    d="m488.832 344.32-339.84 356.672a32 32 0 0 0 0 44.16l.384.384a29.44 29.44 0 0 0 42.688 0l320-335.872 319.872 335.872a29.44 29.44 0 0 0 42.688 0l.384-.384a32 32 0 0 0 0-44.16L535.168 344.32a32 32 0 0 0-46.336 0">
                                                </path>
                                            </svg>
                                        </i>
                                    ) : (
                                        <>{addIcon}</>
                                    )
                                }
                            </div>
                            <div className={["pe-input-number-position-icon", reduceFlag ? 'pe-input-number-disabled' : ''].join(" ").trim()}
                                onClick={() => {
                                    reduce()
                                }}>
                                {
                                    !reduceIcon ? (
                                        <i className="pe-icon">
                                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                                <path fill="currentColor"
                                                    d="M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z">
                                                </path>
                                            </svg>
                                        </i>
                                    ) : (
                                        <>{reduceIcon}</>
                                    )
                                }
                            </div>
                        </div>
                    ) : null
                }
            </div>
            {
                controlsPosition === 'default' && controls ? (
                    <div className={["pe-input-number-icon pe-input-number-right", addFlag ? 'pe-input-number-disabled' : ''].join(" ").trim()}
                        onClick={() => {
                            add()
                        }}>
                        {
                            !addIcon ? (
                                <i className="pe-icon">
                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                        <path fill="currentColor"
                                            d="M480 480V128a32 32 0 0 1 64 0v352h352a32 32 0 1 1 0 64H544v352a32 32 0 1 1-64 0V544H128a32 32 0 0 1 0-64z">
                                        </path>
                                    </svg>
                                </i>
                            ) : (
                                <>{addIcon}</>
                            )
                        }
                    </div>
                ) : null
            }
            {
                disabled ? <div className="pe-disabled"></div> : null
            }
        </div>
    )
}

export default InputNumber